home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The AGA Experience 3
/
AGA Experience Volume 3 (1997)(NFA - SAdENESS)[!].iso
/
software
/
utilities
/
graphics
/
raylab
/
source
/
preproc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-16
|
9KB
|
331 lines
/*
name: preproc.c
Preprocessing
-------------
This part will do as much optimizing as possible before the
actual rendering takes place. Not much is done here, but it
was introduced so that more stuff can be added later (such
as more automatic bounding, and octree subdivision).
This source-code is part of the RayLab 1.1 package, and it is provided
for your compiling pleasure. You may use it, change it, re-compile it
etc., as long as nobody else but you receive the changes/compilations
that you have made!
You may not use any part(s) of this source-code for your own productions
without the permission from the author of RayLab. Please read the legal
information found in the users documentation for RayLab for more details.
*/
#include <stdlib.h>
#include "defs.h"
#include "extern.h"
/* ---------------------------------------------------------------------
Preprocess()
--------------------------------------------------------------------- */
void Preprocess(void)
{
fprintf(textoutput,"Preprocessing...");
OptimizeAllTransforms();
AutoBoundObjects();
RemoveAllUselessTextureTransforms();
if((NeedNoise==TRUE)&&(RenderMethod!=RENDER_QUICKSCAN)) {
InitNoiseTable(); /* Initialize table for noise functions */
}
RndSeed=9761532L; /* Initialize jitter seed */
fprintf(textoutput,"done\n\n");
}
/* ---------------------------------------------------------------------
OptimizeAllTransforms() Optimizes all possible transforms
--------------------------------------------------------------------- */
void OptimizeAllTransforms(void)
{
int i;
for(i=0;i<NumObjects;i++) OptimizeObjTransforms(ObjectArray[i]);
for(i=0;i<Num24Images;i++) OptimizeTransform(&Img24Array[i]->Transform);
for(i=0;i<Num8Images;i++) OptimizeTransform(&Img8Array[i]->Transform);
}
/* ---------------------------------------------------------------------
OptimizeObjTransforms() Optimizes object transforms
(recursively for CSG's)
--------------------------------------------------------------------- */
void OptimizeObjTransforms(OBJECT *Obj)
{
CSG *csg;
if(Obj->ShapeType==SHAPE_CSG) {
csg=(CSG *)Obj->Shape;
OptimizeObjTransforms(csg->Object1);
OptimizeObjTransforms(csg->Object2);
}
OptimizeTransform(&Obj->Transform);
OptimizeTransform(&Obj->Texture.Transform);
}
/* ---------------------------------------------------------------------
OptimizeTransform() Optimizes a single transform
--------------------------------------------------------------------- */
void OptimizeTransform(TRANSFORM *Trans)
{
int i,j,k,TType,Combined;
/* Try to combine successive transfroms of the same kind */
i=0;
while(i<Trans->NumTransforms) {
Combined=FALSE;
j=i+1;
if(j<Trans->NumTransforms) {
TType=Trans->Entry[i].Type;
if(TType==Trans->Entry[j].Type) {
if(TType==TRANSFORM_MOVE) {
Trans->Entry[i].Values.x+=Trans->Entry[j].Values.x;
Trans->Entry[i].Values.y+=Trans->Entry[j].Values.y;
Trans->Entry[i].Values.z+=Trans->Entry[j].Values.z;
Combined=TRUE;
}
if(TType==TRANSFORM_SCALE) {
Trans->Entry[i].Values.x*=Trans->Entry[j].Values.x;
Trans->Entry[i].Values.y*=Trans->Entry[j].Values.y;
Trans->Entry[i].Values.z*=Trans->Entry[j].Values.z;
Combined=TRUE;
}
if(Combined==TRUE) {
if(j<(Trans->NumTransforms-1)) {
for(k=j+1;k<Trans->NumTransforms;k++) {
Trans->Entry[k-1]=Trans->Entry[k];
}
}
Trans->NumTransforms--;
}
}
}
if(Combined==FALSE) i++;
}
}
/* ---------------------------------------------------------------------
AutoBoundObjects() calls routines for automatic bounding.
--------------------------------------------------------------------- */
void AutoBoundObjects(void)
{
OBJECT *Obj;
int i;
for(i=0;i<NumObjects;i++) {
Obj=ObjectArray[i];
if(Obj->BoundType==BOUND_NONE) {
switch (Obj->ShapeType) {
case SHAPE_TRIANGLELIST:
BoundTriangleList(Obj);
break;
default:
break;
}
}
}
}
/* ---------------------------------------------------------------------
BoundTriangleList() determines the optimal bounding box for
a given triangle list object.
--------------------------------------------------------------------- */
void BoundTriangleList(OBJECT *Obj)
{
VECTOR min,max,corners[3];
BOX *BBox;
TRIANGLELIST *Tri;
register double tnx,tny,tnz;
int i;
min.x=min.y=min.z=50000.0;
max.x=max.y=max.z=-50000.0;
Tri=(TRIANGLELIST *)Obj->Shape;
while(Tri!=NULL) {
tnx=Tri->Normal.x; tny=Tri->Normal.y; tnz=Tri->Normal.z;
switch (Tri->Projection) {
case PROJ_XY:
for(i=0;i<3;i++) {
corners[i].x=Tri->Corners[i].u;
corners[i].y=Tri->Corners[i].v;
corners[i].z=-(tnx*Tri->Corners[i].u+tny*Tri->Corners[i].v)/tnz;
}
break;
case PROJ_XZ:
for(i=0;i<3;i++) {
corners[i].x=Tri->Corners[i].u;
corners[i].z=Tri->Corners[i].v;
corners[i].y=-(tnx*Tri->Corners[i].u+tnz*Tri->Corners[i].v)/tny;
}
break;
case PROJ_YZ:
for(i=0;i<3;i++) {
corners[i].y=Tri->Corners[i].u;
corners[i].z=Tri->Corners[i].v;
corners[i].x=-(tny*Tri->Corners[i].u+tnz*Tri->Corners[i].v)/tnx;
}
break;
}
for(i=0;i<3;i++) {
if(corners[i].x<min.x) min.x=corners[i].x;
if(corners[i].x>max.x) max.x=corners[i].x;
if(corners[i].y<min.y) min.y=corners[i].y;
if(corners[i].y>max.y) max.y=corners[i].y;
if(corners[i].z<min.z) min.z=corners[i].z;
if(corners[i].z>max.z) max.z=corners[i].z;
}
Tri=Tri->NextTriangle;
}
if((BBox=(BOX *)malloc(sizeof(BOX)))!=NULL) {
CopyPoint(&BBox->Corners[0],(POINT *)&min);
CopyPoint(&BBox->Corners[1],(POINT *)&max);
Obj->BoundType=BOUND_BOX;
Obj->Bound=(void *)BBox;
TransformBounding(Obj, &Obj->Transform);
}
}
/* ---------------------------------------------------------------------
TransformBounding() determines the optimal bounding volume
after it has been transformed.
--------------------------------------------------------------------- */
void TransformBounding(OBJECT *Obj, TRANSFORM *Trans)
{
BOX *Box;
SPHERE *Sphere;
POINT BoxCorners[8];
VECTOR Radius;
double MaxRadius;
int i;
if((Obj->BoundType == BOUND_BOX)||(Obj->BoundType == BOUND_TMPBOX)) {
Box = (BOX *)Obj->Bound;
for(i=0;i<8;i++) {
BoxCorners[i].x = Box->Corners[i&0x01].x;
BoxCorners[i].y = Box->Corners[(i>>1)&0x01].y;
BoxCorners[i].z = Box->Corners[(i>>2)&0x01].z;
}
Box->Corners[0].x = Box->Corners[0].y = Box->Corners[0].z = maxcoord;
Box->Corners[1].x = Box->Corners[1].y = Box->Corners[1].z = mincoord;
for(i=0;i<8;i++) {
ForwdTransformPoint(&BoxCorners[i], Trans);
if(BoxCorners[i].x<Box->Corners[0].x) Box->Corners[0].x = BoxCorners[i].x;
if(BoxCorners[i].y<Box->Corners[0].y) Box->Corners[0].y = BoxCorners[i].y;
if(BoxCorners[i].z<Box->Corners[0].z) Box->Corners[0].z = BoxCorners[i].z;
if(BoxCorners[i].x>Box->Corners[1].x) Box->Corners[1].x = BoxCorners[i].x;
if(BoxCorners[i].y>Box->Corners[1].y) Box->Corners[1].y = BoxCorners[i].y;
if(BoxCorners[i].z>Box->Corners[1].z) Box->Corners[1].z = BoxCorners[i].z;
}
}
else if(Obj->BoundType == BOUND_SPHERE) {
Sphere = (SPHERE *)Obj->Bound;
ForwdTransformPoint(&Sphere->Centre, Trans);
MaxRadius = Sphere->r;
if(Trans->NumTransforms>0) {
for(i=0;i<Trans->NumTransforms;i++) {
Radius.x = Radius.y = Radius.z = MaxRadius;
if(Trans->Entry[i].Type == TRANSFORM_SCALE) {
Radius.x *= Trans->Entry[i].Values.x;
Radius.y *= Trans->Entry[i].Values.y;
Radius.z *= Trans->Entry[i].Values.z;
MaxRadius = Radius.x;
if(Radius.y>MaxRadius) MaxRadius = Radius.y;
if(Radius.z>MaxRadius) MaxRadius = Radius.z;
}
}
}
Sphere->r = MaxRadius;
}
}
/* ---------------------------------------------------------------------
RemoveAllUselessTextureTransforms() will remove texture transforms
from textures that do not contain patterns or images.
--------------------------------------------------------------------- */
void RemoveAllUselessTextureTransforms(void)
{
int i;
for(i=0;i<NumObjects;i++)
RemoveUselessTextureTransforms(ObjectArray[i]);
}
void RemoveUselessTextureTransforms(OBJECT *Obj)
{
if(Obj->ShapeType == SHAPE_CSG) {
RemoveUselessTextureTransforms(((CSG *)Obj->Shape)->Object1);
RemoveUselessTextureTransforms(((CSG *)Obj->Shape)->Object2);
}
else {
if( (Obj->Texture.Pattern == PATTERN_NONE) &&
(Obj->Texture.ImageType == IMG_NONE)) {
ClearTransform(&Obj->Texture.Transform);
}
}
}
/* ---------------------------------------------------------------------
ForwdTransformPoint() I needed this, so here it is...
--------------------------------------------------------------------- */
void ForwdTransformPoint(POINT *Point, TRANSFORM *Trans)
{
VECTOR tempv;
int i;
if(Trans->NumTransforms>0) {
for(i=0;i<Trans->NumTransforms;i++) {
switch(Trans->Entry[i].Type) {
case TRANSFORM_SCALE:
tempv=Trans->Entry[i].Values;
Point->x*=tempv.x; Point->y*=tempv.y; Point->z*=tempv.z;
break;
case TRANSFORM_MOVE:
AddVector((VECTOR *)Point,(VECTOR *)Point,&Trans->Entry[i].Values);
break;
case TRANSFORM_ROTATE:
RotatePoint(Point,&Trans->Entry[i].Values);
break;
case TRANSFORM_NONE:
default:
break;
}
}
}
}